﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JtextEpicsInterface;
using string_short;
using System.Threading;

namespace DummyDriver
{
    public class Dummy:IEJDriver
    {
        //this class is used to send and recieve messages from message-based device and DO NOT process it. then hand to EJserver
            //this is also a template to make you own drivers
            //you1don't have to follow the whole structrue
            //for detials and which function is critical look for the document
        //this is only a dummy driver that does nothing
            const int OUTMSG_TIMEOUT = 50;

            protected bool IsByte;    //if the cmd is byte or string
            private int CMDLen; //the lenth of the cmd used in byte cmd
            private byte CMDEnd;    //the end char  of the cmd used in byte cmd

            public delegate void MSGArrivedHandler(byte[] MyMessage);
            MSGArrivedHandler MsgArrived = null;    //listenner will invoke this when message arived

            public event DriverCrashHandler OnDriverCrash;


            //call the message Arrived function in EJServer not this class
            //this is decleared in JtextEpicsInterface
            public event SendToEJServerHandler  OnSendToEJServer;

            public delegate void ListenerHandler();
            ListenerHandler MyListener = null;
            Thread ListenerThread;  //the listener thread

            //Thread ListenerThread;  //the listener thread

            //async call the out message to the port ,couse you will not know when willit return
            public delegate int OutMSGHandler(byte[] MyMessage);
            OutMSGHandler OutMSG = null;

            private object DrvIniObj;   //the drvier decription

            #region Dummy additional Objects
            private object LockFlag;
            private bool hasDataFlag;   //use this two indecate data arrived
            private bool isConsole;
            //private SerialPort MySPort; //
            string myName = "DummyDriver";
            #endregion



            public Dummy()
            {
                MsgArrived = new MSGArrivedHandler(MessageArrived);
                isConsole = false;
            }

            //this will set the property of the drivers the first few argument are used to decripe the common proporties
            //that allEJDrivers would have the last argument usually is a string that used to contain Driver specified info like hardware settings
            public void SetDriver(bool isByte, int len, byte end, object IniObj)
            {
                OutMSG = new OutMSGHandler(Out_msg);
                MsgArrived = new MSGArrivedHandler(MessageArrived);
                //SendtoEJServer = SendtoEJS;
                LockFlag = new object();
                IsByte = isByte;
                CMDLen = len;
                CMDEnd = end;

                //customized code
                hasDataFlag = false;
                if (IniObj == null)
                {
                    //DrvIniObj = new serialDesc();
                    //default driver setting
                    DrvIniObj = "Dummy";
                }
                else
                {
                    DrvIniObj = IniObj;
                }
            }

            public void IniDriver()
            {
                
                try
                {
                   //Console.WriteLine("PortOpen(B201010091546)");
                    Console.WriteLine("Dummy Hohoho~~");
                    if ((string)DrvIniObj=="console")
                    {
                        Console.WriteLine("In Console");
                        isConsole = true;
                        StartListener();
                    }
                }
                catch
                {
                    
                }

                //customized code end
                //dummy do not listen to anything
                //this.StartListener();

                //start listener here
            }



            public void StopDriver()
            {
                //ListenerThread.Suspend();
            }

            #region send the message

            public int Send_msg(string message_str)
            {

                Console.WriteLine(message_str);
                return 0;   //returns the status ,if the message is successfully send out   //called by EJServer
            }

            public int Send_msg(byte[] message_byte)
            {

                string Tmsg = Str_Short.BytesToHexString(message_byte,";");
                Console.WriteLine(Tmsg);
                return 0;   //returns the status ,if the message is successfully send out //called by EJServer
            }

            #region simple proc
            //the message used to be done here 
            //now is done by plugin so this only transfer string to byte
            private static byte[] Proc_msg(string messager_str)
            {
                //proccess the message tobe sent
                //test code
                Encoding my_ASC = Encoding.ASCII;
                return my_ASC.GetBytes(messager_str);
            }

            private static byte[] Proc_msg(byte[] messager_byte)
            {
                //proccess the message tobe sent
                //test code
                return messager_byte;
            }
            #endregion

            private int Out_msg(byte[] MyMessage)
            {


                return 0;
            }


            #endregion

            #region recieve message

            public  byte[] Proc_MSG_In(byte[] myMessage)
            {
                //proccess the incoming message
                //Console.WriteLine("proc");
                Encoding my_ASC = Encoding.ASCII;
                if (IsByte == false)
                {
                    string tMsg = my_ASC.GetString(myMessage);
                    Console.WriteLine("Msg Comes:" + tMsg);
                    return myMessage;
                }
                else
                {
                    
                    string tMsg = my_ASC.GetString(myMessage);
                    Console.WriteLine("Msg Comes:" + tMsg);
                    byte[] msgRT = Str_Short.HexStringToBytes(tMsg, ";");
                    return msgRT;
                }
                return myMessage;
            }


            #endregion


            #region linstening
            
        
            private void MessageArrived(byte[] MyMessage)
            {
                //listenner will invoke this when got message
                Console.WriteLine("!!!" );
                if (OnSendToEJServer != null)
                {
                    //Console.WriteLine("444!");
                    byte[] TMsg = Proc_MSG_In(MyMessage);
                    //Console.WriteLine("555!");
                    OnSendToEJServer(TMsg);
                    //Console.WriteLine("666!");
                }
            }



            private void StartListener()
            {   //start the listener
                if (ListenerThread == null)
                {
                    ListenerThread = new Thread(new ThreadStart(this.Listener));
                    ListenerThread.Start();
                }
                else
                {
                    try
                    {
                        ListenerThread.Resume();
                    }
                    catch
                    {
                        throw new System.Exception("Can not start ListenerThread");
                    }
                }
            }


            private void Listener()
            {
                Encoding my_ASC = Encoding.ASCII;
                while (true)
                {
                    if (isConsole == false)
                    {
                        return;
                    }
                    else
                    {
                        Console.WriteLine("start Listen");
                        string Tmsg = Console.ReadLine();
                        byte [] TbMsg=my_ASC.GetBytes(Tmsg);
                        Console.WriteLine("Msg Comes");
                        MsgArrived.BeginInvoke(TbMsg, null, null);
                    }
                }
            }

            #endregion

            #region property
            public string DriverName
            {
                get { return myName; }
            }

            #endregion


    }
}
